#ifndef __syntax_attribute_H__
#define __syntax_attribute_H__

#include "util.h"
#include "expression.h"

namespace syntax_analysis
{

#define NOT_SET		UNKNOWN

	enum syntax_match_type
	{
		MIN_MATCH = 1 << 0,
		MAX_MATCH = 1 << 1,
		TAKE_STRING = 1 << 2,
		DONT_TAKE_STRING = 1 << 3,
	};
	
	class syntax_attribute
	{
	public:
		syntax_attribute()
		{
			m_min = NULL;
			m_max = NULL;
			m_real = NOT_SET;
			m_match_type = MAX_MATCH | TAKE_STRING;
		}

		syntax_attribute( 
			expression *exp_min, 
			expression *exp_max, 
			int match_type, 
			int real = NOT_SET )
		{
			m_min = exp_min;
			m_max = exp_max;
			m_match_type = match_type;
			m_real = real;
		}

		virtual ~syntax_attribute()
		{
			if( m_min != NULL )
				delete m_min;
			if( m_max != NULL )
				delete m_max;
			m_min = NULL;
			m_max = NULL;
			m_real = NOT_SET;
			m_match_type = MAX_MATCH | TAKE_STRING;
		}

		string to_string()
		{
			string syn;
			int nmin;
			int nmax;
			if( m_min != NULL && m_max != NULL )
			{
				syn = "[";
				nmin = m_min->get_value();
				nmax = m_max->get_value();
				if( nmin == EXP_ALL )
					syn += "*";
				else if( nmin == EXP_ONE_MORE )
					syn += "+";
				else
					syn += util::to_string( nmin );
				syn += ",";
				if( nmax == EXP_ALL )
					syn += "*";
				else if( nmax == EXP_ONE_MORE )
					syn += "+";
				else
					syn += util::to_string( nmax );
				syn += "]";
			}
			else if( m_min != NULL )
			{
				syn = "[";
				nmin = m_min->get_value();
				if( nmin == EXP_ALL )
					syn += "*";
				else if( nmin == EXP_ONE_MORE )
					syn += "+";
				else
					syn += util::to_string( nmin );
				syn += "]";
			}
			if( ( m_match_type & (MIN_MATCH|DONT_TAKE_STRING) ) == (MIN_MATCH|DONT_TAKE_STRING) )
				syn += "(min_match,dont_take)";
			else if( ( m_match_type & MIN_MATCH ) == MIN_MATCH )
				syn += "(min_match)";
			else if( ( m_match_type & DONT_TAKE_STRING ) == DONT_TAKE_STRING )
				syn += "(dont_take)";
			return syn;
		}

	public:
		int get_min()
		{
			if( m_min != NULL )
				return m_min->get_value();
			else
				return 1;
		}

		void set_min( expression *exp_min )
		{
			if( m_min != NULL )
				delete m_min;
			m_min = exp_min;
		}

		int get_max()
		{
			if( m_max != NULL )
				return m_max->get_value();
			else if( m_min != NULL )
				return NOT_SET;
			else
				return get_min();
		}

		void set_max( expression *exp_max )
		{
			if( m_max != NULL )
				delete m_max;
			m_max = exp_max;
		}

		int get_real()
		{
			return m_real;
		}

		void set_real( int real )
		{
			m_real = real;
		}

		int get_match_type()
		{
			return m_match_type;
		}

		void set_match_type( int type )
		{
			m_match_type = type;
		}

	private:
		expression *m_min;
		expression *m_max;
		int m_real;
		int m_match_type;
	};

}

#endif // __syntax_attribute_h__
